﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.ServiceModel;
using System.Windows.Shapes;
using Dimok;

namespace CollectionInfo {
	public partial class Page : UserControl {
		public Page() {
			var e = new Elite.Silverlight3.MouseWheelSample.Silverlight.Classes.MouseWheelScrollBehavior();
			var il = new MBC.UI.ImageList();
			InitializeComponent();
			LayoutRoot.DataContext = new CollectionInfoModel();
		}

		private void Window_Loaded(object sender, RoutedEventArgs e) {
			//((CollectionInfoModel)DataContext).LoadCollectionInfo("1AF123328");
			try {
				if (Parent == null && LayoutRoot.DataContext is CollectionInfoModel)
					HtmlPage.RegisterScriptableObject("DataContext", LayoutRoot.DataContext as CollectionInfoModel);
			} catch (InvalidOperationException) { }
		}
		[ScriptableMember]
		public void LoadCollectionInfo(string VantageID) {
			((CollectionInfoModel)LayoutRoot.DataContext).LoadCollectionInfo(VantageID);
		}



		public string VantageID {
			get { return (string)GetValue(VantageIDProperty); }
			set { SetValue(VantageIDProperty, value); }
		}

		// Using a DependencyProperty as the backing store for VantageID.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty VantageIDProperty =
				DependencyProperty.Register("VantageID", typeof(string), typeof(Page), new PropertyMetadata(VantageIDChangedCallback));

		static void VantageIDChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			var p = d as Page;
			if (p == null) throw new Exception(d.GetType().FullName + " is not " + typeof(Page).FullName);
			var lr = p.FindName("LayoutRoot") as FrameworkElement;
			var dc = lr.DataContext as CollectionInfoModel;
			if (dc == null)
				lr.DataContext = dc = new CollectionInfoModel();
			dc.VantageID = e.NewValue + "";
		}


	}

	public class DataBindingTooltip {
		public static DependencyProperty TooltipProperty;

		static DataBindingTooltip() {
			TooltipProperty = DependencyProperty.RegisterAttached
					("Tooltip", typeof(object),
					typeof(DataBindingTooltip),
					new PropertyMetadata(TooltipChanged));
		}

		public static void SetTooltip(DependencyObject d, object value) {
			d.SetValue(DataBindingTooltip.TooltipProperty, value);
		}

		public static object GetToolTip(DependencyObject d) {
			return d.GetValue(DataBindingTooltip.TooltipProperty);
		}

		private static void TooltipChanged(DependencyObject sender,
				DependencyPropertyChangedEventArgs e) {
			if (sender is FrameworkElement) {
				FrameworkElement owner = sender as FrameworkElement;
				// wait for it to be in the visual tree so that
				// context can be established
				owner.Loaded += new RoutedEventHandler(owner_Loaded);
			}

		}

		static void owner_Loaded(object sender, RoutedEventArgs e) {
			if (sender is FrameworkElement) {
				FrameworkElement owner = sender as FrameworkElement;
				// remove the event handler
				owner.Loaded -= new RoutedEventHandler(owner_Loaded);

				DependencyObject tooltip =
						owner.GetValue(DataBindingTooltip.TooltipProperty) as DependencyObject;
				if (tooltip != null) {
					// assign the data context of the current owner control to the tooltip's datacontext
					tooltip.SetValue(FrameworkElement.DataContextProperty,
							owner.GetValue(FrameworkElement.DataContextProperty));
				}
				ToolTipService.SetToolTip(owner, tooltip);
			}
		}
	}

	/// <summary>
	/// Replica of ToolTipService class with support for attaching DataContext from parent dependency object if target and source
	/// are both framework elements.  Actual tooltip management is delegated to the ToolTipService
	/// </summary>

	#region ToolTipManager
	public static class ToolTipManager {

		#region Dependency Properties

		/// <summary>
		/// Attached property against which a visual tooltip tree can be registered
		/// </summary>

		public static readonly DependencyProperty ToolTipProperty =
				DependencyProperty.RegisterAttached("ToolTip", typeof(FrameworkElement), typeof(ToolTipManager),
														new PropertyMetadata(new PropertyChangedCallback(ToolTipManager.OnToolTipChanged)));

		/// <summary>
		/// Hidden dependency property that enables us to receive notifications when the source data context changes and 
		/// needs to be flushed into the context of the tooltip
		/// </summary>

		private static readonly DependencyProperty DataContextProperty =
				DependencyProperty.RegisterAttached("DataContext", typeof(object), typeof(ToolTipManager),
														new PropertyMetadata(new PropertyChangedCallback(ToolTipManager.OnDataContextChanged)));

		#endregion

		#region Dependency Property getter and setters

		public static FrameworkElement GetToolTip(DependencyObject obj) {
			return (FrameworkElement)obj.GetValue(ToolTipManager.ToolTipProperty);
		}

		public static void SetToolTip(DependencyObject obj, FrameworkElement element) {
			obj.SetValue(ToolTipManager.ToolTipProperty, element);
		}

		#endregion

		#region OnToolTipChanged

		private static void OnToolTipChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {

			// If the attached dependency object and tooltip are framework elements copy the data context from the 
			// depObj to the tooltip to simplify binding

			var sfe = sender as FrameworkElement;
			var tfe = e.NewValue as FrameworkElement;

			if (object.ReferenceEquals(null, sfe) || object.ReferenceEquals(null, tfe)) return;

			// The data context probably is not assigned at this stage so hook up for the change notification.  

			tfe.DataContext = sfe.DataContext;

			sfe.SetBinding(ToolTipManager.DataContextProperty, new Binding());

			ToolTipService.SetToolTip(sender, e.NewValue);
		}

		#endregion

		#region OnDataContextChanged

		public static void OnDataContextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {

			// Called whenever the data context on an attached object is changed ... we need to switch the context to the 
			// dependent tool tip element

			var sfe = sender as FrameworkElement;
			var tfe = ToolTipManager.GetToolTip(sender) as FrameworkElement;

			//Debug.Assert(!(object.ReferenceEquals(null, sfe) || object.ReferenceEquals(null, tfe)), "Unexpected null reference to attached FrameworkElement");

			tfe.DataContext = sfe.DataContext;

			// TODO: Would ideally prefer to detach a tooltip without a data context and then reattach it when the new one is added but
			// resetting it throws an internal hresult exception (presumably as it is already part of the visual tree?) so we can't
			// Downside is that the tooltip may show an empty window if the data context is not known

			//if(object.ReferenceEquals(null, tfe.DataContext))
			//    ToolTipService.SetToolTip(sender, null);
			//else
			//    ToolTipService.SetToolTip(sender, tfe);
		}

		#endregion

	}
	#endregion

	#region Helper
	public class Helpers {

		public static string GetToolTipContent(DependencyObject obj) {
			return (string)obj.GetValue(ToolTipContentProperty);
		}

		public static void SetToolTipContent(DependencyObject obj,
																					string value) {
			obj.SetValue(ToolTipContentProperty, value);
		}

		public static readonly DependencyProperty
		ToolTipContentProperty =
			DependencyProperty.RegisterAttached(
				"ToolTipContent",
				typeof(string),
				typeof(Helpers),
				new PropertyMetadata(OnToolTipContentChangedCallback));

		private static void OnToolTipContentChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			var tt = (ContentControl)ToolTipService.GetToolTip(d);
			tt.Content = e.NewValue.ToString();
			ToolTipService.SetToolTip(d, tt);
		}
	}
	#endregion

}
